package pri.hillchen.std.concurrent.chapter14.boundedbuffer;

import pri.hillchen.std.concurrent.chapter14.boundedbuffer.exception.BufferEmptyException;
import pri.hillchen.std.concurrent.chapter14.boundedbuffer.exception.BufferFullException;

import java.util.concurrent.TimeUnit;

/**
 * @author:hillchen
 * @DESCRIPTION:
 * @Date: Created in 10:13 2018/2/13 0013.
 */
public class SyncBoundedBuffer<V> extends BaseBoundedBuffer<V> {
    public SyncBoundedBuffer(int capacity) {
        super(capacity);
    }

    public synchronized void put(V ele) throws BufferFullException {
        if(isFull()){
            throw new BufferFullException("缓存已满，不能添加，请等待！");
        }
        doPut(ele);
    }

    public synchronized V take() throws BufferEmptyException {
        if(isEmpty()){
           throw new BufferEmptyException("缓存已满，不能添加，请等待！");
        }
        return doTake();
    }

    public static void main(String[] args) throws InterruptedException {
        class BufferTest<T>{
            void putTest(SyncBoundedBuffer<T>  boundedBuffer, T ele, long timeout, TimeUnit timeUnit) throws InterruptedException {
                while (true){
                    try {
                        boundedBuffer.put(ele);
                        return;
                    }catch (BufferFullException e){
                        timeUnit.sleep(timeout);
                    }
                }
            }

            T takeTest(SyncBoundedBuffer<T>  boundedBuffer, long timeout, TimeUnit timeUnit) throws InterruptedException {
                while (true){
                    try {
                        return boundedBuffer.take();
                    }catch (BufferEmptyException e){
                        timeUnit.sleep(timeout);
                    }
                }
            }
        }

        SyncBoundedBuffer<Integer> syncBoundedBuffer = new SyncBoundedBuffer<>(10);
        BufferTest<Integer> integerBufferTest = new BufferTest<Integer>();
        for(int i = 0; i<10;i++){
            integerBufferTest.putTest(syncBoundedBuffer,i,1,TimeUnit.NANOSECONDS);
        }
        for(int i = 0; i<10;i++){
            System.out.println(integerBufferTest.takeTest(syncBoundedBuffer,1,TimeUnit.NANOSECONDS));
        }
    }
}
